<?php

declare(strict_types=1);

namespace Modules\DataCheck\Http\Controllers;

use Catch\Exceptions\FailedException;
use Catch\Exceptions\TokenExpiredException;
use Catch\Facade\Admin;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Modules\DataCheck\Enums\TaskStateEnum;
use Modules\DataCheck\Excel\Export\DcTaskExport;
use Modules\DataCheck\Http\Requests\DcTaskRequest;
use Modules\DataCheck\Http\Requests\DcTaskUpdateRequest;
use Modules\DataCheck\Models\DcTask;
use Modules\DataCheck\Models\DcTaskSourceFile;
use Modules\DataCheck\Services\TaskService;
use Pro\Support\Helper;
use Illuminate\Support\Facades\Log;
/**
 * @class DcTaskController
 */
class DcTaskController extends BaseController
{
    /**
     * @param DcTask $model
     */
    public function __construct(protected readonly DcTask $model)
    {
    }

    /**
     * 列表
     *
     * @return mixed
     */
    public function index(Request $request): mixed
    {
        //  `task_state` 任务状态 1=待核对 2=核对排队中 3=核对中 4=核对完成 5=核对失败 6=停止核对 64=停止核对(核对成功) 65=停止核对(核对失败)'
        $taskState = $request->input('task_state');
        if($taskState && $taskState == TaskStateEnum::RUNNING->value){
            $request->merge(['task_state' => [2,3]]);
        }
        if($taskState && $taskState == TaskStateEnum::STOP->value){
            $request->merge(['task_state' => [6,61,64,65]]);
        }
        //获取当前用户登录身份
        $currentUser = Admin::currentLoginUser();
        //使用CatchAdmin规范：通过setBeforeGetList处理关联关系，然后返回分页数据
        $paginator =  $this->model->setBeforeGetList(function ($query) use($request,$currentUser) {
            // 构建查询关联关系
            $query->from('dc_task')
                ->leftJoin('dc_task_source_file', 'dc_task.source_file_id', '=', 'dc_task_source_file.id')
                ->leftJoin('admin_users', 'dc_task.creator_id', '=', 'admin_users.id');
            //选择需要返回的字段
            $query->select([
                'dc_task.id AS id',
                'dc_task.task_id',
                'dc_task.task_name',
                'dc_task.target_file',
                'dc_task.file_download_count',
                'dc_task.task_state',
                'dc_task.task_remark',
                'dc_task.created_at',
                'dc_task_source_file.id AS source_file_id',
                'dc_task_source_file.file_name AS source_file_original_name',
                'dc_task_source_file.file_state AS source_file_state',
                'dc_task_source_file.remark AS source_file_remark',
                'admin_users.username AS creator'
            ]);
            //如果登录不是不是超管或者业务超管则只查询当前用户创建的记录·
             $userRoleIds = $currentUser->roles()->pluck('role_id')->toArray();
//            if (!in_array(config('catch.business_admin'),$userRoleIds ) && !in_array(config('catch.super_admin'),$userRoleIds )){
//                $query->where('dc_task.creator_id', $currentUser->id);
//            }
            //增加查询条件
            if($taskState = $request->input('task_state')){
                if(is_array($taskState)){
                    $query->whereIn('dc_task.task_state', $taskState);
                }else{
                    $query->where('dc_task.task_state', $taskState);
                }
            }
            //模糊查询任务名称
            if($taskName = $request->input('task_name')){
                $query->where('dc_task.task_name', 'like', '%'.$taskName.'%');
            }
            return $query;
        })->getList();
        // 获取分页信息用于序列号计算
        $currentPage = $paginator->currentPage(); // 当前页码（从 1 开始）
        $perPage = $paginator->perPage(); // 每页显示的条数

        // 对结果集进行后处理，添加序列号和格式化时间字段
        $paginator->getCollection()->transform(function ($item, $index) use ($currentPage, $perPage) {
            // 计算并添加序列号：(当前页-1)*每页条数 + 索引（从0开始） + 1
            $serialNumber = ($currentPage - 1) * $perPage + $index + 1;
            $item->serial_number = $serialNumber;
            if($item->task_remark){
                $taskRemark = Helper::jsonToArray($item->task_remark);
                $item->task_remark = $taskRemark['msg']??'';
            }
            if($item->source_file_remark){
                $taskRemark = Helper::jsonToArray($item->source_file_remark);
                $item->source_file_remark = $taskRemark['msg']??'';
            }
            $item->target_file_original_name = $item->target_file['file_name']?? '';
            //补充数据结构 TODO:后面进行删除
            $item->source_file = [
                'id'=>$item->source_file_id,
                'file_name'=>$item->source_file_original_name,
                'file_state'=>$item->source_file_state
            ];
            return $item;
        });

        return $paginator;
    }

    /*
    public function indexOld(Request $request): mixed
    {
        //如果 $request->input(‘task_state’) 等于3， 则在数据库查询的时候 需要改为 $query->where('task_state', [2,3] );
        // 使用CatchAdmin规范：通过setBeforeGetList处理关联关系，然后返回分页数据
//        $request->input('task_state')
        $request->merge(['task_state' => '3']);
        return $this->model->setBeforeGetList(function ($query) {
            $query->with(['sourceFile' => function ($query) {
                $query->select('id', 'file_name', 'file_state');
            }]);//SELECT id, file_name, file_state FROM dc_task_source_file  WHERE id IN (1, 3, 5)
            return $query;
        })->getList();
    }*/

    /**
     * 保存数据
     *
     * @param DcTaskRequest $request
     * @return mixed
     */
    public function store(DcTaskRequest $request): mixed
    {
        //获取登录用户uid
        $operatorUid = Admin::id();
        // 获取验证通过的数据
        $data = $request->validated();
        //处理源文件 - 根据source_file_id判断处理方式
        $sourceFileId = $data['source_file_id'] ?? 0;
        if ($sourceFileId && $sourceFileId > 0) { //如果传入了有效的source_file_id，直接使用历史记录文件
            $sourceFile = DcTaskSourceFile::select('id', 'file_name', 'file_path')
                ->where('created_user_id', $operatorUid)
                ->where('file_state', 3)
                ->where('id', $sourceFileId)
                ->first();
            if (!$sourceFile) {
                throw new FailedException('指定的总表文件不存在');
            }
            $data['source_file'] = $sourceFile->file_path;
        }
        // 使用CatchModel内置的事务处理
        $taskId = uniqid();
        try {
            $this->model->transaction(function () use ($taskId,$operatorUid,$sourceFileId,$data) {
                //判断是否需要创建总表文件记录
                if (empty($sourceFileId) && !empty($data['source_file'])) {
                    $fileData = app(TaskService::class)->createSourceFile($operatorUid, $data['source_file_original_name'], $data['source_file']);
                    $sourceFileId = $fileData['source_file_id'];
                }
                $taskData = [
                    'task_id' => $taskId,
                    'task_name' => $data['task_name'],
                    'source_file_id' => $sourceFileId,
                    'target_file' => [
                        'file_name' => $data['target_file_original_name'],
                        'file_path' => $data['target_file'],
                    ],
                    'task_state' => 1,
                    'task_remark' => '',
                    'file_download_count' => 0,
                ];
                // 4. 使用CatchModel的storeBy方法创建任务记录
                $this->model->storeBy($taskData);
            });
        } catch (\Exception $e) {
            // 记录异常日志
            Log::error('创建数据核对任务失败: ' . $e->getMessage(), [
                'task_name' => $data['task_name'],
                'operator_uid' => $operatorUid,
                'trace' => $e->getTraceAsString()
            ]);
            throw new FailedException('创建数据核对任务失败: ' . $e->getMessage());
        }
        //记录管理员行为
        request()->attributes->set('behavior', [
            'module'     => '数据核对',
            'business'   => '任务管理',
            'operation'  => "创建数据核对任务（任务id：{$taskId}  任务名称：{$data['task_name']}）",
            'related_id' => $taskId
        ]);
        return ['task_id' => $taskId];
    }

    /**
     * 展示数据
     *
     * @param mixed $id
     * @return mixed
     */
    public function show(mixed $id): mixed
    {
        // 查询任务信息
        $task = $this->model->where('id', $id)->select(['id','task_id','task_id','task_name','source_file_id','target_file'])->first();
        if (empty($task)) {
            throw new FailedException('任务不存在');
        }
        //查询源数据信息
        $sourceFile = DcTaskSourceFile::select('id', 'file_name', 'file_path')->where('id', $task->source_file_id)->first();
        //处理数据信息
        return [
            'id'                        => $task->id,
            'task_id'                   => $task->task_id,
            'task_name'                 => $task->task_name,
            'target_file_original_name' => $task->target_file ? $task->target_file['file_name'] : '',
            'target_file'               => $task->target_file ? $task->target_file['file_path'] : '',
            'source_file_id'            => $task->source_file_id,
            'source_file_original_name' => $sourceFile ? $sourceFile->file_name : '',
            'source_file'               => $sourceFile ? $sourceFile->file_path : '',
        ];
    }


    public function update(mixed $id, Request $request): mixed
    {
        //获取登录用户uid
        $operatorUid = Admin::id();
        //参数接收
        $taskName = $request->input('task_name');
        $targetFileOriginalName = $request->input('target_file_original_name');
        $targetFile = $request->input('target_file');
        $sourceFileId = $request->input('source_file_id');
        $sourceFileOriginalName = $request->input('source_file_original_name');
        $sourceFile = $request->input('source_file');
        //$taskName必填
        if (empty($taskName)) {
            throw new FailedException('任务名称不能为空');
        }
        //判断核查文件收正确
        if (empty($targetFileOriginalName) || empty($targetFile)) {
            throw new FailedException('请上传核查文件');
        }
        // 当source_file_id为空或为0时，则 source_file_original_name 和 source_file 必须传递
        if ((!$sourceFileId || $sourceFileId == 0) && (empty($sourceFileOriginalName) || empty($sourceFile))) {
            throw new FailedException('当未选择历史文件时，必须上传新的目标文件');
        }
        // 查询任务信息
        $task = $this->model->where('id', $id)->select(['task_id','task_state','creator_id'])->first();
        if (empty($task)) {
            throw new FailedException('任务不存在');
        }
        if($task->creator_id != $operatorUid){
            throw new FailedException('无权限操作此任务');
        }
        // 检查任务状态
        if($task->task_state == TaskStateEnum::COMPLETE->value){
            throw new FailedException('任务已完成，无法修改');
        }
        if(in_array($task->task_state, [TaskStateEnum::WAIT_RUNNING->value, TaskStateEnum::RUNNING->value] )){
            throw new FailedException('任务正在执行中，无法修改');
        }
        //判断源文件是否存在，如果传入了有效的source_file_id，直接使用历史记录文件
        if($sourceFileId){
            $sourceFile = DcTaskSourceFile::select('id', 'file_name', 'file_path','created_user_id')->find($sourceFileId);
            if (!$sourceFile || $sourceFile->created_user_id != $operatorUid) {
                throw new FailedException('指定的总表文件不存在');
            }
        }

        // 开启事务进行下载统计和日志记录
        $this->model->beginTransaction();
        try{
           // 判断是否需要创建新的总表文件记录
            if (empty($sourceFileId)){
                $fileData = app(TaskService::class)->createSourceFile($operatorUid, $sourceFileOriginalName, $sourceFile);
                $sourceFileId = $fileData['source_file_id'];
            }
            //2.处理目标文件信息
            $baseData = [
                'task_name'           => $taskName,
                'source_file_id'      => $sourceFileId,
                'target_file'         => [
                    'file_name' => $targetFileOriginalName,
                    'file_path' => $targetFile,
                ],
                'file_download_count' => 0,
                'file_download_url'   => '',
                'task_state'          => 1,
                'task_remark'         => '',
            ];
            $this->model->updateBy($id, $baseData);
            //提交事务
            $this->model->commit();
        }catch (\Throwable $e){
            // 回滚事务并抛出异常
            $this->model->rollBack();
            throw new FailedException("更新数据核对任务失败：".$e->getMessage());
        }
        //记录管理员行为
        request()->attributes->set('behavior', [
            'module'     => '数据核对',
            'business'   => '任务管理',
            'operation'  => "更新数据核对任务（任务id：{$task->task_id}）",
            'related_id' => $task->task_id
        ]);
        return [];

    }

    /**
     * 删除数据
     *
     * @param mixed $id
     * @return mixed
     */
    public function destroy(mixed $id, Request $request): mixed
    {
        //获取登录用户uid
        $operatorUid = Admin::id();
        // 查询任务信息
        $task = $this->model->where('id', $id)->select(['task_id','task_state','creator_id'])->first();
        if (empty($task)) {
            throw new FailedException('任务不存在');
        }
        if($task->creator_id != $operatorUid){
            throw new FailedException('无权限操作此任务');
        }
        //记录管理员行为
        request()->attributes->set('behavior', [
            'module'     => '数据核对',
            'business'   => '任务管理',
            'operation'  => "删除数据核对任务（任务id：{$task->task_id}）",
            'related_id' => $task->task_id
        ]);
        return $this->model->deleteBy($id);
    }

    /**
     * 获取目标文件历史记录
     *
     * @param Request $request
     * @return mixed
     */
    public function history(Request $request): mixed
    {
        // 获取当前登录用户ID
        $currentUser = Admin::currentLoginUser();
        $currentUserId = $currentUser ? $currentUser['id'] : null;
        if (!$currentUserId) {
             throw new TokenExpiredException('Token已过期，请重新登录');
        }
        // 从dc_task_source_file表中获取当前用户的数据
        $historyFiles = DcTaskSourceFile::where('created_user_id', $currentUserId)->where('file_state',3)
            ->orderBy('last_used_time', 'desc')
            ->orderBy('id', 'desc')
            ->limit(1)
            ->get()
            ->map(function ($file) {
                return [
                    'id' => $file->id,
                    'name' => $file->file_name,
                    'path' => $file->file_path,
                    'last_used_time' => $file->created_at->format('Y-m-d H:i:s'),
                ];
            })
            ->toArray();
        // 按照CatchAdmin规范，直接返回数据，让框架自动处理响应格式
        return $historyFiles;
    }
    /**
     * 导出
     *
     * @param Request $request
     * @param DcTaskExport $export
     * @return mixed
     */
    public function export(Request $request, DcTaskExport $export): mixed
    {
        // 验证task_id参数
        $taskId = $request->input('task_id');
        if (empty($taskId)) {
            return $this->error('任务ID不能为空');
        }

        // 查找任务
        $task = $this->model->where('task_id', $taskId)->first();
        if (!$task) {
            return $this->error('任务不存在');
        }

        try {
            // 调用导出处理方法
            $result = $export->handle($task);
            return $this->success($result, '导出成功');
        } catch (\Exception $e) {
            return $this->error('导出失败：' . $e->getMessage());
        }
    }
}
